#!/usr/bin/env bash

# Test script code thanks to coreos/etcd
#
# Run all tests
# ./test
# ./test -v
#
# Run also integration tests
# INTEGRATION=1 STOLON_TEST_STORE_BACKEND=etcdv3 ./test
#
set -e

source $(dirname $0)/scripts/readlinkdashf.sh
BASEDIR=$(readlinkdashf $(dirname $0))
BINDIR=${BASEDIR}/bin

if [ $PWD != $BASEDIR ]; then
	cd $BASEDIR
fi

ORG_PATH="github.com/sorintlab"
REPO_PATH="${ORG_PATH}/stolon"

# test all packages excluding integration tests
IGNORE_PKGS="(vendor/|tests/integration)"
PACKAGES=$(find . -name \*_test.go | while read -r a; do dirname "$a"; done | sort | uniq | grep -vE "$IGNORE_PKGS" | sed "s|\./||g")

# prepend REPO_PATH to each local package
split=$PACKAGES
PACKAGES=""
for a in $split; do PACKAGES="$PACKAGES ${REPO_PATH}/${a}"; done

echo "Running tests..."

COVER=${COVER:-"-cover"}

## Use this code in case we are testing with multiple go versions that have different gofmt outputs
# # Use only of specific go version to run gofmt since it'll break when some formatting rules change between versions
# GOFMT_VERSION="go1.14"
# MAJOR_GOVERSION=$( echo -n $(go version) | grep -o 'go1\.[0-9]*' || true )
# if [ "${MAJOR_GOVERSION}" == "${GOFMT_VERSION}" ]; then
# 	echo "Checking gofmt..."
# 	fmtRes=$(gofmt -l $(find . -type f -name '*.go' ! -path './vendor/*' ! -path '*/\.*'))
# 	if [ -n "${fmtRes}" ]; then
# 		echo -e "gofmt checking failed:\n${fmtRes}"
# 		exit 255
# 	fi
# fi

echo "Checking gofmt..."
fmtRes=$(gofmt -l $(find . -type f -name '*.go' ! -path './vendor/*' ! -path '*/\.*'))
if [ -n "${fmtRes}" ]; then
	echo -e "gofmt checking failed:\n${fmtRes}"
	exit 255
fi

echo "Checking govet..."
vetRes=$(go vet ${PACKAGES})
if [ -n "${vetRes}" ]; then
	echo -e "govet checking failed:\n${vetRes}"
	exit 255
fi

echo "Checking govet -shadow ..."
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
export PATH="$(go env GOPATH)/bin":${PATH}
shadow_tool=$(which shadow)
vetRes=$(${shadow_tool} ${PACKAGES})
if [ -n "${vetRes}" ]; then
	echo -e "govet checking ${path} failed:\n${vetRes}"
	exit 255
fi

echo "Checking for license header..."
licRes=$(for file in $(find . -type f -iname '*.go' ! -path './vendor/*'); do
		head -n3 "${file}" | grep -Eq "(Copyright|generated|GENERATED)" || echo -e "  ${file}"
	done;)
if [ -n "${licRes}" ]; then
	echo -e "license header checking failed:\n${licRes}"
	exit 255
fi


echo "Checking with golangci-lint"
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b ${BINDIR} v1.23.6
${BINDIR}/golangci-lint run --deadline 5m

echo "Running tests"
go test -timeout 3m ${COVER} $@ ${PACKAGES} ${RACE}

if [ -n "$INTEGRATION" ]; then
	echo "Running integration tests..."
	if [ -z ${STOLON_TEST_STORE_BACKEND} ]; then
		echo "STOLON_TEST_STORE_BACKEND env var needs to be defined (etcd or consul)"
		exit 1
	fi
	export STKEEPER_BIN=${BINDIR}/stolon-keeper
	export STSENTINEL_BIN=${BINDIR}/stolon-sentinel
	export STPROXY_BIN=${BINDIR}/stolon-proxy
	export STCTL_BIN=${BINDIR}/stolonctl
	if [ "${STOLON_TEST_STORE_BACKEND}" == "etcd" -o "${STOLON_TEST_STORE_BACKEND}" == "etcdv2" -o "${STOLON_TEST_STORE_BACKEND}" == "etcdv3" ]; then
		if [ -z ${ETCD_BIN} ]; then
			if [ -z $(which etcd) ]; then
				echo "cannot find etcd in PATH and ETCD_BIN environment variable not defined"
				exit 1
			fi
			ETCD_BIN=$(which etcd)
		fi
		echo "using etcd from $ETCD_BIN"
		export ETCD_BIN
	elif [ "${STOLON_TEST_STORE_BACKEND}" == "consul" ]; then
		if [ -z ${CONSUL_BIN} ]; then
			if [ -z $(which consul) ]; then
				echo "cannot find consul in PATH and CONSUL_BIN environment variable not defined"
				exit 1
			fi
			CONSUL_BIN=$(which consul)
		fi
		echo "using consul from $CONSUL_BIN"
		export CONSUL_BIN
	else
		echo "Unknown store backend: \"${STOLON_TEST_STORE_BACKEND}\""
		exit 1
	fi

	[ -z "$PARALLEL" ] && PARALLEL=4
	go test -timeout 20m $@ -v -count 1 -parallel ${PARALLEL} ${REPO_PATH}/tests/integration
fi

echo "Success"
